/* 
 * Copyright (C) 2015 fede
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package Control;

import Entity.Event;
import Entity.NotifyLink;
import Entity.NotifyReply;
import Entity.RegisteredUser;
import java.security.Principal;
import java.util.List;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;

/**
 *
 * @author fede
 */
@Stateless
public class EventFacade extends AbstractFacade<Event> {

    @PersistenceContext(unitName = "meteocal")
    EntityManager em;

    /**
     * get entity manager
     *
     * @return entity manager of the class
     */
    @Override
    protected EntityManager getEntityManager() {
        return em;
    }

    @EJB
    private RegisteredUserFacade ruf;

    @EJB
    private NotifyReplyFacade nrf;

    @EJB
    private NotifyLinkFacade nlf;

    @EJB
    private CalendarFacade cf;

    @Inject
    Principal principal;

    /**
     * This method add an event to DB
     *
     * @param event to add
     * @param guest list of invitedUser
     */
    public void save(Event event, List<RegisteredUser> guest) {
        addNotifyReply(event, guest);
        cf.addEvent(event);
        em.persist(event);
    }

    /**
     * This method remove an event to DB
     *
     * @param eventId ID of the event to delete
     */
    public void delete(String eventId) {
        Event toRemove = em.getReference(Event.class, eventId);
        removeNotifyLink(eventId);
        removeNotifyReply(eventId);
        cf.deleteEvent(toRemove);
        em.remove(toRemove);
    }

    /**
     * This method update an event to DB
     *
     * @param event to add
     * @param guest list of invitedUser
     */
    public void editE(Event event, List<RegisteredUser> guest) {
        removeNotifyReply(event.getId());
        removeNotifyLink(event.getId());
        addNotifyReply(event, guest);
        getEntityManager().merge(event);
    }

    /**
     * this method get all public or private event
     *
     * @param pubBool true=public, false=private
     * @return List of Event
     */
    public List<Event> getAllPublicEvent(Boolean pubBool) {
        TypedQuery<Event> query = em.createNamedQuery(Event.FIND_ALL_PUBLIC, Event.class);
        query.setParameter("pubBool", pubBool);
        query.setParameter("id", principal.getName());
        return query.getResultList();
    }

    /**
     * this method get all public or private event on public or private calendar
     *
     * @param pubBoolCal true=public, false=private
     * @param pubBoolEv true=public, false=private
     * @return List of event
     */
    public List<Event> getAllPublicCalendarEvent(Boolean pubBoolCal, Boolean pubBoolEv) {
        TypedQuery<Event> query = em.createNamedQuery(Event.FIND_ALL_CALENDAR, Event.class);
        query.setParameter("pubBoolCal", pubBoolCal);
        query.setParameter("pubBoolEv", pubBoolEv);
        query.setParameter("id", principal.getName());
        return query.getResultList();
    }

    /**
     * this method get all event where the user has been invited
     *
     * @return List of event
     */
    public List<Event> getAllInvited() {
        TypedQuery<Event> query = em.createNamedQuery(Event.FIND_ALL_INVITED, Event.class);
        query.setParameter("id", ruf.getLoggedUser());
        List<Event> temp = query.getResultList();
        TypedQuery<NotifyReply> query1 = em.createNamedQuery(NotifyReply.FIND_ALL, NotifyReply.class);
        List<NotifyReply> temp2;
        for (int i = 0; i < temp.size(); i++) {
            query1.setParameter("eventId", temp.get(i).getId());
            query1.setParameter("user", principal.getName());
            temp2 = query1.getResultList();
            if (temp2.size() > 0) {
                temp.remove(i);
                i--;

            }
        }

        return temp;
    }

    /**
     * This method remove the invited user for an event
     *
     * @param notifyReply to delete
     */
    public void removeInvitedUser(NotifyReply notifyReply) {
        em.find(Event.class, notifyReply.getEvent().getId()).getGuest().remove(ruf.getLoggedUser());

    }

    private void removeNotifyReply(String eventId) {
        TypedQuery<NotifyReply> query = em.createNamedQuery(NotifyReply.FIND_ALL_EVENT, NotifyReply.class);
        query.setParameter("eventId", eventId);
        for (NotifyReply resultList : query.getResultList()) {
            nrf.remove(resultList);
        }

    }

    private void removeNotifyLink(String eventId) {

        TypedQuery<NotifyLink> query = em.createNamedQuery(NotifyLink.FIND_ALL, NotifyLink.class);
        query.setParameter("eventId", eventId);

        for (NotifyLink resultList : query.getResultList()) {
            nlf.remove(resultList);
        }
    }

    private void addNotifyReply(Event event, List<RegisteredUser> guest) {
        event.setOwner(ruf.getLoggedUser());
        if (guest != null && guest.size() > 0) {
            event.setGuest(guest);
            for (int i = 0; i < guest.size(); i++) {
                nrf.createNotify(event, guest.get(i));
            }

        }

    }

    /**
     * constructor
     */
    public EventFacade() {
        super(Event.class);
    }

}
